Spring Security | Note-13

Spring Security Note-13


开发APP认证框架

基于服务器

在之前的学习中,我们所保存的用户信息,Session等都是保存在服务器中的;

用户通过浏览器,每次访问服务的时候,服务器都会检查浏览器的Cookies中是否包含JSESSIONID;

如果不包含JSESSIONID,就会新建一个SESSION,新建的SESSION就会写到Cookies中,每次用户请求时,都会去检查SESSION,拿出用户的信息;

更新换代

前后端分离的服务,将HTML服务与应用服务分离开,单独部署到Web Server上;

在这种部署模式下,用户通过浏览器直接访问的是Web Server而不是Application Server,然后针对HTML的渲染由Web Server完成,ajax请求发给Web Server之后,再向Application Server发送请求,拿到数据;

不管是APP还是前后端分离的部署,最根本的出现就是:

用户不再是通过浏览器直接访问应用

而是通过第三方应用(APP,Web Server)

在这种架构模式下,继续使用Cookies和Session就会出现问题:

1.开发繁琐(浏览器已经封装好)

2.安全性和客户体验差(认证工作由服务器完成,SESSION失效与登录)

3.有些前端技术不支持Cookies(微信小程序)

Spring Security OAuth

解决这种架构下的方法,其中一种是通过令牌(Token)的方式解决;

令牌是一种类似SESSION的唯一标识,在SESSION模式下,是往Cookies中写入JSESSIONID,而令牌是直接发给用户一个唯一标识的Token,用户每次访问带着令牌,Application Server去认证自身发出的令牌;

-

在接下来的开发过程中,开发和认证的方式,就改变成了令牌的收发和认证,使用OAuth协议来解决开发问题;

在OAuth协议中,Spring Social封装了大部分的开发内容,直接使用就可以完成第三方应用Client基本功能;

接下来学习的Spring Security OAuth则是封装了服务提供商的绝大部分行为,可以实现发令牌,认证令牌;

-

为了完成服务提供商的功能,我们需要实现认证服务器和资源服务器的功能;

在认证服务器中,需要完成4种授权模式,确认用户的身份和权限,通过4种授权模式,根据这些信息生成Token和存储;

在资源服务器下,我们需要保护资源(REST服务),通过Spring Security的过滤器链进行保护,在Spring Security OAuth中,通过在过滤器链上加入OAuth2AuthenticationProcessingFilter的方式,对请求中拿出Token,在存储策略中进行认证;

在实际开发中,我们不希望用户通过4种标准的授权模式(手机短信),我们希望通过自定义的认证方式,在认证服务器中实现认证;


实现标准的OAuth2服务提供商(Provider)

1.首先我们将SimpleRespon移动到Core项目当中;

2.将BrowserSecurityConfig的PasswordEncoder移动到Core项目的SecurityCoreConfig;

认证服务器
1
2
3
4
@Configuration
@EnableAuthorizationServer
public class ImoocAuthorizationServerConfig {
}
资源服务器
1
2
3
4
@Configuration
@EnableResourceServer
public class ImoocResourceServerConfig {
}

-

访问四种授权模式

访问/oauth/authorize 需要附带参数:

response_type : code

client_id : xxx

redirect_uri : http://

scope : all

启动时默认生成的

1
2
security.oauth2.client.client-id = 64f9b36e-d819-4526-8047-d6f80cf16123
security.oauth2.client.client-secret = 1d5527b0-33f8-4a9d-8536-312ff78d69d0
在配置文件中配置
1
2
security.oauth2.client.client-id=imooc
security.oauth2.client.client-secret=imoocsecret
修改MyUserDetailService

添加ROLE_USER的角色(默认必须有这个角色)

1
2
3
4
5
6
7
8
9
private SocialUserDetails buildUser(String username) {
// TODO 根据用户名(数据库)查找用户信息
// 根据查找到的用户信息,判断用户是否被冻结
String password = passwordEncoder.encode("123456");
logger.info("PASSWORD FROM DB : " + password);
return new SocialUser(username, password,
true, true, true, true,
AuthorityUtils.commaSeparatedStringToAuthorityList("admin,ROLE_USER"));
}

-

授权码模式
获取授权码

http://localhost:8060/oauth/authorize?response_type=code&client_id=imooc&redirect_uri=http://example.com&scope=all

在工具内验证授权码模式请求:

返回结果

-

密码模式
发送请求

返回结果

-

获取用户信息

对比我们可以发现,在expires_in没过期的前提下,同一个用户在两种授权模式下的access_token是一样的;

401

在不附带参数的情况下,获取用户数据的话,会报出401的错误;

-

200

当我们获取到access_token之后,就可以通过access_token & token_type获取用户信息;